package io.plus.user_interface.redis;

import drds.common.$;
import io.plus.user_interface.io.common.utils.JsonKit;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

//import org.apache.commons.lang3.StringUtils;

@Data
@Slf4j
public class CacheImpl implements Cache {

    private String cacheName = null;
    private Integer timeToLiveSeconds = null;
    private Integer timeToIdleSeconds = null;
    private Integer timeout = null;

    public CacheImpl(String cacheName, Integer timeToLiveSeconds, Integer timeToIdleSeconds) {
        this.cacheName = cacheName;
        this.timeToLiveSeconds = timeToLiveSeconds;
        this.timeToIdleSeconds = timeToIdleSeconds;
        this.timeout = this.timeToLiveSeconds == null ? this.timeToIdleSeconds : this.timeToLiveSeconds;

    }

    public static String cacheKey(String cacheName, String key) {
        return keyPrefix(cacheName) + key;
    }

    public static String keyPrefix(String cacheName) {
        return cacheName + ":";
    }

    @Override
    public void clear() {
        try {
            JedisTemplate.me().delKeysLike(keyPrefix(cacheName));
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        log.info("clear cache {} ok", cacheName);
    }

    @Override
    public Serializable get(String key) {
        if ($.isNullOrEmpty(key)) {
            return null;
        }
        Serializable value = null;
        try {
            value = JedisTemplate.me().get(cacheKey(cacheName, key), Serializable.class);
            if (timeToIdleSeconds != null) {
                if (value != null) {
                    ExpireTask.add(cacheName, key, value, timeout);
                }
            }
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return value;
    }

    @Override
    public <T> T get(String key, Class<T> clazz) {
        if ($.isNullOrEmpty(key)) {
            return null;
        }
        T value = null;
        try {
            value = JedisTemplate.me().get(cacheKey(cacheName, key), clazz);
            if (timeToIdleSeconds != null) {
                if (value != null) {
                    ExpireTask.add(cacheName, key, (Serializable) value, timeout);
                }
            }
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return value;
    }

    @Override
    public Collection<String> keys() {
        try {
            return JedisTemplate.me().keys(keyPrefix(cacheName));
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return null;
    }

    public List<String> listGetAll(String key) {
        if ($.isNullOrEmpty(key)) {
            return null;
        }
        try {
            return JedisTemplate.me().listGetAll(cacheKey(cacheName, key));
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return null;
    }

    public void listPushTail(String key, Serializable value) {
        if ($.isNullOrEmpty(key)) {
            return;
        }
        try {
            String jsonValue = value instanceof String ? (String) value : JsonKit.toJSONString(value);
            JedisTemplate.me().listPushTail(cacheKey(cacheName, key), jsonValue);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
    }

    public Long listRemove(String key, String value) {
        if ($.isNullOrEmpty(key) || $.isNullOrEmpty(value)) {
            return 0L;
        }
        try {
            return JedisTemplate.me().listRemove(cacheKey(cacheName, key), 0, value);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return 0L;
    }

    @Override
    public void put(String key, Serializable value) {
        if ($.isNullOrEmpty(key)) {
            return;
        }
        try {
            JedisTemplate.me().set(cacheKey(cacheName, key), value, Integer.parseInt(timeout + ""));
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
    }

    public void putAll(List<JedisTemplate.Pair<String, Serializable>> values) {
        if (values == null || values.size() < 1) {
            return;
        }
        int expire = Integer.parseInt(timeout + "");
        try {
            List<JedisTemplate.ExpirePair<String, String, Integer>> pairDatas = new ArrayList<JedisTemplate.ExpirePair<String, String, Integer>>();
            for (JedisTemplate.Pair<String, Serializable> pair : values) {
                pairDatas.add(JedisTemplate.me().makePairEx(cacheKey(cacheName, pair.getKey()), JsonKit.toJSONString(pair.getValue()), expire));
            }
            JedisTemplate.me().batchSetStringEx(pairDatas);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
    }

    @Override
    public void putTemporaryValue(String key, Serializable value) {
        if ($.isNullOrEmpty(key)) {
            return;
        }
        try {
            JedisTemplate.me().set(cacheKey(cacheName, key), value, 10);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
    }

    @Override
    public void remove(String key) {
        if ($.isNullOrEmpty(key)) {
            return;
        }
        try {
            JedisTemplate.me().delKey(cacheKey(cacheName, key));
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
    }

    public List<String> sortSetGetAll(String key) {
        if ($.isNullOrEmpty(key)) {
            return null;
        }
        try {
            Set<String> dataSet = JedisTemplate.me().sorSetRangeByScore(cacheKey(cacheName, key), Double.MIN_VALUE, Double.MAX_VALUE);
            if (dataSet == null) {
                return null;
            }
            return new ArrayList<String>(dataSet);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return null;
    }

    public List<String> sortSetGetAll(String key, double min, double max) {
        if ($.isNullOrEmpty(key)) {
            return null;
        }
        try {
            Set<String> dataSet = JedisTemplate.me().sorSetRangeByScore(cacheKey(cacheName, key), min, max);
            if (dataSet == null) {
                return null;
            }
            return new ArrayList<String>(dataSet);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return null;
    }

    public List<String> sortSetGetAll(String key, double min, double max, int offset, int count) {
        if ($.isNullOrEmpty(key)) {
            return null;
        }
        try {
            Set<String> dataSet = JedisTemplate.me().sorSetRangeByScore(cacheKey(cacheName, key), min, max, offset, count);
            if (dataSet == null) {
                return null;
            }
            return new ArrayList<String>(dataSet);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return null;
    }

    public void sortSetPush(String key, double score, Serializable value) {
        if ($.isNullOrEmpty(key)) {
            return;
        }
        try {
            String jsonValue = value instanceof String ? (String) value : JsonKit.toJSONString(value);
            JedisTemplate.me().sortSetPush(cacheKey(cacheName, key), score, jsonValue);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
    }
}
